import { HttpException, HttpStatus, Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { FindOneOptions, type Repository } from 'typeorm'
import { UserEntity, PostEntity } from '../../entitys'
import { I_Response } from '../../types/type'
import { UpdateUserDto } from './dtos/Response.dto'
import { QueryPage } from '../apiProperty'

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private readonly userRepository: Repository<UserEntity>,
    @InjectRepository(PostEntity)
    private readonly postRepository: Repository<PostEntity>
  ) {}

  async findOne(
    id: string,
    configs: FindOneOptions<UserEntity> = {}
  ): Promise<UserEntity> {
    const { select = [], ...config } = configs
    try {
      const user = await this.userRepository.findOne({
        comment: `根据 ID ${id} 查询用户信息`,
        where: { id },
        ...config
      })
      if (user?.id) return user
    } catch (error) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR)
    }
    return null
  }

  async getUserInfoById(id: string): Promise<I_Response<unknown>> {
    const user = await this.findOne(id)
    if (user?.id) return { data: user }
    return { success: false, code: 400, message: '' }
  }

  async updateUserInfo(
    id: string,
    body: UpdateUserDto
  ): Promise<I_Response<unknown>> {
    try {
      const keys = {
        age: true,
        avatar: true,
        description: true,
        email: true,
        mobile: true,
        nickname: true,
        sex: true
      }
      const time = new Date(Date.now() + 1000 * 60 * 60 * 8).toISOString()
      const user = {
        id,
        updateAt: time.substring(0, time.indexOf('.'))?.replace(/t/gi, ' ')
      }
      for (const key in body) {
        if (Object.prototype.hasOwnProperty.call(body, key)) {
          if (keys[key]) {
            user[key] =
              key !== 'sex' && key !== 'age'
                ? body[key]?.toString()?.replace(/script/gi, 'code')
                : body[key]
          }
        }
      }
      const { affected } = await this.userRepository.update({ id }, user)
      return {
        message: affected ? '修改成功' : '修改失败',
        data: user
      }
    } catch (error) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR)
    }
  }

  async userFollowsInfo(
    id: string,
    query: QueryPage
  ): Promise<I_Response<unknown>> {
    const { pageIndex = '1', pageSize = '10' } = query
    const user = await this.findOne(id, {
      relations: {
        follows: true
      }
    })

    user.follows = user.follows.splice(
      (parseInt(pageIndex) - 1) * parseInt(pageSize),
      parseInt(pageSize) + (parseInt(pageIndex) - 1) * parseInt(pageSize)
    )

    return { data: user.follows }
  }

  async followsUser(
    id: string,
    followId: string
  ): Promise<I_Response<unknown>> {
    const user = await this.findOne(id, {
      relations: {
        follows: true
      }
    })
    if (user.follows.some(item => item.id === followId)) {
      return {
        message: '已关注该用户',
        code: 400,
        success: false
      }
    }
    const follow = await this.findOne(followId)
    user.follows.push(follow)
    await this.userRepository.save(user)
    return { message: '关注成功' }
  }

  async unfollowUser(
    id: string,
    followId: string
  ): Promise<I_Response<unknown>> {
    const user = await this.findOne(id, {
      relations: {
        follows: true
      }
    })
    if (user.follows.some(item => item.id === followId)) {
      user.follows = user.follows.filter(item => item.id !== followId)
      await this.userRepository.save(user)
      return { message: '已取消关注' }
    }
    return { message: '取消失败, 未关注该用户', code: 400, success: false }
  }

  async userComments(
    id: string,
    query: QueryPage
  ): Promise<I_Response<unknown>> {
    const { pageIndex = '1', pageSize = '10' } = query
    const user = await this.findOne(id, {
      relations: {
        postComment: true
      }
    })
    user.postComment = user.postComment.splice(
      (parseInt(pageIndex) - 1) * parseInt(pageSize),
      parseInt(pageSize) + (parseInt(pageIndex) - 1) * parseInt(pageSize)
    )
    return { data: user.postComment }
  }

  async userStar(id: string, query: QueryPage): Promise<I_Response<unknown>> {
    const { pageIndex = '1', pageSize = '10' } = query
    const user = await this.findOne(id, {
      relations: {
        likePosts: true
      }
    })
    user.likePosts = user.likePosts.splice(
      (parseInt(pageIndex) - 1) * parseInt(pageSize),
      parseInt(pageSize) + (parseInt(pageIndex) - 1) * parseInt(pageSize)
    )
    return { data: user.likePosts }
  }
}
